﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using FRL.DebtChased.Extensions;
using FRL.DebtChased.Repository;
using FRL.DebtChased.Silverlight.Library;
using FRL.DebtChased.Silverlight.Library.RichContentService;
using FRL.DebtChased.Types;

namespace FRL.DebtChased.ChaseWorkspace
{

	/// <summary>
	/// Declaration of InstalmentPlannerPanelCtrl class
	/// Control for setting up an instalment plan
	/// </summary>
	public partial class InstalmentPlannerPanelCtrl : UserControl
	{

		/////////////////////////////////////////////////////////////
		// Atrributes

		private bool m_bBlockEvents = true;

		private Money m_mnAccountTotal;

		private Money m_mnChasableTotal;

		private AccountTransport m_account;

		private InstalmentCalculator m_lastGoodCalc = null;


		/////////////////////////////////////////////////////////////
		// Construction

		public InstalmentPlannerPanelCtrl()
		{

			// Load xaml resources
			InitializeComponent();

			// Set controls - cboPaymentMethod
			ComboBoxObject.LoadFromEnumeration(cboPaymentMethod,typeof(Definitions.eInstalmentPaymentMethod),0);
			cboPaymentMethod.SelectedIndex = 0;

			// Set controls - drpInstalmentCount
			ObservableCollection<string> countList = new ObservableCollection<string>();
			countList.Add("1");
			countList.Add("2");
			countList.Add("3");
			countList.Add("4");
			countList.Add("5");
			countList.Add("6");
			countList.Add("7");
			countList.Add("8");
			countList.Add("9");
			countList.Add("10");
			countList.Add("11");
			countList.Add("12");
			//drpInstalmentCount.StringList = countList;
			//drpInstalmentCount.Text = "6";

			// Clear block
			m_bBlockEvents = false;

		}

		/////////////////////////////////////////////////////////////
		// Event handlers

		private void butConfirm_Click(object sender, RoutedEventArgs e)
		{

			// Check for valid calculation
			if (m_lastGoodCalc == null)
			{
				MessageBoxes.PopupMessage("A valid calculation has not been performed, or the parameters have been changed since the last calculation.");
				return;
			}

			// Get period and payment method
			Definitions.eInstalmentPaymentMethod PaymentMethod = (Definitions.eInstalmentPaymentMethod) (cboPaymentMethod.SelectedItem as ComboBoxObject).ItemData;
			Frequency.ePeriod Period = (Frequency.ePeriod) (instalmentStartDateCtrl.cboPeriod.SelectedItem as ComboBoxObject).ItemData;

			// Build a plan
			AccountPlanTransport newPlan = new AccountPlanTransport();
			newPlan.AccountId = m_account.AccountId;
			newPlan.AccountInvoiceStatusId = (cboInstalmentStatus.SelectedItem as ComboBoxObject).ItemData;
			newPlan.IsActive = true;
			newPlan.PaymentMethod = (int)Period;
			newPlan.Period = (int)PaymentMethod;
			newPlan.ConfirmedAt = DateTime.Now;

			// Add payments
			newPlan.Payments = new ObservableCollection<AccountPlanPaymentTransport>();
			foreach (AccountPlanPaymentTransport payment in m_lastGoodCalc.Payments)
			{
#if DEBUG
				Debug.Assert(payment.Currency != null);
#endif // #if DEBUG
				newPlan.Payments.Add(payment);
			}

			// Confirm with user
			if (!MessageBoxes.PopupOption("Apply the instalment plan?"))
				return;

			// Show hourglass
			MainPage.Singleton.ShowHourglass(true);

			// Send to server for processing
			RichContentServiceClient proxy = new RichContentServiceClient();
			proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
			proxy.SetActiveAccountPlanCompleted += new EventHandler<SetActiveAccountPlanCompletedEventArgs>(proxy_SetActiveAccountPlanCompleted);
			proxy.SetActiveAccountPlanAsync(newPlan);

		}

		void proxy_SetActiveAccountPlanCompleted(object sender, SetActiveAccountPlanCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.ShowHourglass(false);

			// Get the result
			if (e.Error != null)
				MessageBoxes.PopupMessage(e.Error.Message);
			else if (e.Result != null)
				MessageBoxes.PopupMessage_InternalError(e.Result);
			else
			{

				// Inform main page that account needs reloading
				MainPage.Singleton.ChaseScreen.ReloadContextAccount();

			}

		}

		private void butCalculate_Click(object sender, RoutedEventArgs e)
		{

			// Call sibling function
			_recalcPayments();

		}





		private void instalmentStartDateCtrl_ParametersChanged(object sender, EventArgs e)
		{

			// If any parameters have changed, the calculation is out of date, and should not be applied
			m_lastGoodCalc = null;

		}

		private void TextBoxParameter_TextChanged(object sender, TextChangedEventArgs e)
		{

			// If any parameters have changed, the calculation is out of date, and should not be applied
			m_lastGoodCalc = null;

		}

		private void DropParameter_TextChanged(object sender, RoutedEventArgs e)
		{

			// If any parameters have changed, the calculation is out of date, and should not be applied
			m_lastGoodCalc = null;

		}

		/////////////////////////////////////////////////////////////
		// Operations


		public void PostSupportDataLoad()
		{

			// Load the instalment status list
			foreach (var di in CachedData.Singleton.InstalmentStatusMap)
				cboInstalmentStatus.Items.Add(new ComboBoxObject(di.Value, di.Key, null));
			cboInstalmentStatus.SelectedIndex = 0;

		}

		public void Set(AccountTransport account)
		{

			// Retain the reference for future calculations
			m_account = account;

			// Calculate account and chasable total
			List<Money> accountMoneyList = new List<Money>();
			List<Money> chasableMoneyList = new List<Money>();
			foreach (AccountInvoiceTransport inv in account.AccountInvoices)
			{
				accountMoneyList.Add(new Money(inv.Amount.Amount, inv.Amount.CurrencyCode));
				if(true)
					chasableMoneyList.Add(new Money(inv.Amount.Amount, inv.Amount.CurrencyCode));
			}
			m_mnAccountTotal = Money.Add(accountMoneyList);
			m_mnChasableTotal = Money.Add(chasableMoneyList);
			tbAccountTotal.Text = m_mnAccountTotal.Format(true);
			tbChasableTotal.Text = m_mnAccountTotal.Format(true);

			// Set controls
			cboInstalmentStatus.SelectedIndex = 0;
			cboPaymentMethod.SelectedIndex = 0;


			// Start with 6 instalments, and a 30% first payment, 1/6 regular payments
			drpInstalmentCount.SelectedValue = "6";
			txtFirstPaymentPerc.Text = "";
			double dblRegularPayments = ((double)m_mnChasableTotal.Amount) / 6;
			dblRegularPayments = Math.Round((dblRegularPayments * 100) / 100);
			txtRegularPayment.Text = string.Format("{0:0.00}", dblRegularPayments);



			// Call sibling function
			_recalcPayments();
			
		}

		private void _recalcPayments()
		{

			// Declaration of local variables
			double dblTemp = 0;
			double dblChasableTotal = (double)m_mnChasableTotal.Amount;

			// Reset the last good calc
			m_lastGoodCalc = null;

			// Calculate the first Instalment
			decimal? dcFirstPayment = null;
            if (!string.IsNullOrWhiteSpace(txtFirstPaymentPerc.Text))
			{

				// Calculate first-payment
				dblTemp = 0;
				if (double.TryParse(txtFirstPaymentPerc.Text, out dblTemp))
				{
					dblTemp = (dblTemp * dblChasableTotal) / 100.0;

					// Round up pence
					dblTemp = dblTemp.RoundUpPence();

					// Limit the first payment
					dblTemp = Math.Min(dblChasableTotal, dblTemp);

					// Convert to decimal
					dcFirstPayment = (decimal)dblTemp;

					// Update text
					if (dcFirstPayment == 0)
						txtFirstPaymentAmount.Text = "";
					else
						txtFirstPaymentAmount.Text = string.Format("{0:0.00}", dcFirstPayment);

				}

			}
			else
			{

				// Calculate percentage
				dblTemp = 0;
				if (double.TryParse(txtFirstPaymentAmount.Text, out dblTemp))
				{

					// Round up pence
					dblTemp = dblTemp.RoundUpPence();

					// Convert to decimal
					dcFirstPayment = (decimal)dblTemp;

					// Update percentage text
					dblTemp = (dblTemp * 100.0) / dblChasableTotal;
					if (dblTemp == 0)
						txtFirstPaymentPerc.Text = "";
					else
						txtFirstPaymentPerc.Text = string.Format("{0:0.####}", dblTemp);
				}

			}

			// Get parameters
			int? iInstalmentCount = null;
			decimal? dcRegularPayment = null;
            if (drpInstalmentCount.SelectedValue!=null && !string.IsNullOrWhiteSpace(drpInstalmentCount.SelectedValue.ToString()))
			{

				// Get the Instalment count
				int iInstalments = 0;
				int.TryParse(drpInstalmentCount.SelectedValue.ToString(), out iInstalments);
				iInstalmentCount = Math.Max(1, iInstalments);

			}
			else
			{

				// Get the regular payment
				dblTemp = 0;
				double.TryParse(txtRegularPayment.Text, out dblTemp);
				dcRegularPayment = (decimal)dblTemp.RoundUpPence();

			}

			// Get the frequency
			Frequency frequency = instalmentStartDateCtrl.Get();

			// Declare a calculator
			InstalmentCalculator calc = new InstalmentCalculator();
			string strError = calc.Calculate(
				m_account,
				frequency,
				dcFirstPayment,
				iInstalmentCount,
				dcRegularPayment,
				CachedData.Singleton.CurrentInterestRate
			);
			if (strError == null)
			{

				// Show Instalments
				//drpInstalmentCount.Text = calc.InstalmentCount.ToString();

				// Get invoice currency
				Money.eCurrency currency = Money.ParseCurrencyCode(m_account.AccountInvoices[0].Amount.CurrencyCode);

				// Set rows
				gridPayment.Set(calc, currency);

				// Set controls
				//tbTotalDays.Text = string.Format("{0} days", calc.TotalDays);
				//tbAmountPayable.Text = new Money(calc.TotalPayments, currency).Format(false);
				//tbTotalInterest.Text = new Money(calc.TotalInterestAdded, currency).Format(false);

				// Hide error
				//tbError.Visibility = System.Windows.Visibility.Collapsed;

				// Retain this calc
				m_lastGoodCalc = calc;

			}
			else
			{
				//tbError.Text = strError;
				//tbError.Visibility = System.Windows.Visibility.Visible;
			}
			

		}



	}

}
